﻿using System;

namespace Cpu6502.Opcodes
{
    /// <summary>
    /// LDX #AA - Immediate Mode
    /// Loads Value directly into the X register.
    /// </summary>
    public class LDX_I : Opcode
    {
        public LDX_I()
        {
            this.CpuCycles = 2;
            this.AddressType = CPU.AddressType.Immediate;
        }

        public override void Execute()
        {
            CPU.Registers.X = (byte)base.Argument;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (base.Argument == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((base.Argument << 7) & 1) != 0);   
        }
    }

    /// <summary>
    /// LDX $AAAA - LDX Absolute Mode
    /// Loads Value from memory into Register X
    /// </summary>
    public class LDX_A : Opcode
    {
        public LDX_A()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.Absolute;
        }

        public override void Execute()
        {
            CPU.Registers.X = CPU.Memory[base.Argument];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.X == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.X << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDX $AAAA, Y - LDX Absolute Y Mode
    /// Loads Value from memory into Register X
    /// </summary>
    public class LDX_A_Y : Opcode
    {
        public LDX_A_Y()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedY;
        }

        public override void Execute()
        {
            CPU.Registers.X = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.AbsoluteIndexedY)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.X == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.X << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDX $AA - LDX ZeroPage Mode
    /// Loads Value from memory into register X
    /// </summary>
    public class LDX_ZP : Opcode
    {
        public LDX_ZP()
        {
            this.CpuCycles = 3;
            this.AddressType = CPU.AddressType.ZeroPage;
        }

        public override void Execute()
        {
            CPU.Registers.X =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPage)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.X == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.X << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDX $AA, Y - LDX ZeroPage Y Mode
    /// Loads Value from memory into Register X
    /// </summary>
    public class LDX_ZP_Y : Opcode
    {
        public LDX_ZP_Y()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.ZeroPageIndexedY;
        }

        public override void Execute()
        {
            CPU.Registers.X =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPageIndexedY)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.X == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.X << 7) & 1) != 0);
        }
    }  

}
